﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace Air_condition.DO
{
    [Serializable]
    public class Room : ICloneable
    {
        #region Attributes
        // Attributes of Room object
        private double dbinsideTemperature;
        private double dboutSideTemperature;
        private double dbinsideVaporContains;
        private double dboutsideVaporContains;
        private double dbwidth;
        private double dbheigh;
        private double dblength;
        private double dbvolume;
        private double dbstandardAir;
        private double dbairCoefficient;
        private int ilocation;
        private string sname;
        public InternalLoad inter = new InternalLoad();
        public Glass gl = new Glass();
        public List<Construction> lConstruction = new List<Construction>();
        public Result res = new Result();

        // Public access to attributes
        public int iLocation
        {
            get { return ilocation; }
            set { ilocation = value; }
        }

        public double dbWidth
        {
            get { return dbwidth; }
            set { dbwidth = value; }
        }

        public double dbHeigh
        {
            get { return dbheigh; }
            set { dbheigh = value; }
        }

        public double dbLength
        {
            get { return dblength; }
            set { dblength = value; }
        }

        public double dbAirCoefficient
        {
            get { return dbairCoefficient; }
            set { dbairCoefficient = value; }
        }

        public double dbInsideTemperature
        {
            get { return dbinsideTemperature; }
            set { dbinsideTemperature = value; }
        }

        public double dbOutSideTemperature
        {
            get { return dboutSideTemperature; }
            set { dboutSideTemperature = value; }
        }

        public double dbVolume
        {
            get { return dbvolume; }
            set { dbvolume = value; }
        }

        public string sName
        {
            get { return sname; }
            set { sname = value; }
        }

        public double dbInsideAirContainingLevel
        {
            get { return dbinsideVaporContains; }
            set { dbinsideVaporContains = value; }
        }

        public double dbOutsideAirContainingLevel
        {
            get { return dboutsideVaporContains; }
            set { dboutsideVaporContains = value; }
        }
        #endregion

        //  Năng suất kho lạnh Qo = Qh + Qa
        /// <summary>
        /// Method to calculate cold productivity of room (Q0)
        /// </summary>
        /// <returns>cold productivity of room</returns>
        public double CalculateColdProductivity()
        {
            double Qh = CalculateSumSensibleHeat();
            double Qa = CalculateSumLatentHeat();
            res.dbSumColdProductivity = Math.Round(Qh + Qa, 1);
            return res.dbSumColdProductivity;
        }

        #region Sensible Heat Calculation
        // Tổng nhiệt hiện Qh = Qhf + QhN
        /// <summary>
        /// Method to calculate sum sensible heat of room (Qh)
        /// </summary>
        /// <returns>sum sensible heat of room</returns>
        public double CalculateSumSensibleHeat()
        {
            double Qhf = CalculateSumRoomSensibleHeat();
            double QhN = CalculateSumOutSideSensibleHeat();
            res.dbSumSensibleHeat = Math.Round(Qhf + QhN, 1);
            return res.dbSumSensibleHeat;
        }

        // Tổng nhiệt hiện của phòng bằng Qhf = (Q11 + Q12 + Q2 + Q31 + Q32 + Q33) phần 1.4.1 Sách
        /// <summary>
        /// Method to calculate sum sensible heat in room (Qhf)
        /// </summary>
        /// <returns>sum sensible heat in room</returns>
        public double CalculateSumRoomSensibleHeat()
        {
            // Calculate radition heat through glass
            double Q11 = gl.CalculateGlassRadiationHeat();
            res.dbGlassRadiationHeat = Math.Round(Q11, 1);

            // Calculate sum heat transfer through construction
            double Q2 = 0;
            foreach (Construction con in lConstruction)
            {
                Q2 += con.CalculateConstructionHeatTransfer(dbinsideTemperature, dbOutSideTemperature);
            }
            res.dbSumConstructionHeatTransfer = Math.Round(Q2, 1);

            // Calculate sensible heat of people
            double Q31 = inter.CalculatePeopleSensibletHeat(dblength * dbwidth);
            res.dbPeopleSensibleHeat = Math.Round(Q31, 1);

            // Calculate sensible heat of light
            double Q32 = inter.CalculateLightSensibleHeat(dblength * dbwidth);
            res.dbLightSensibleHeat = Math.Round(Q32, 1);

            // Calculate sensible heat of equipment
            double Q33 = inter.CalculatePowerToolsSensibleHeat();
            res.dbPowerToolsSensibleHeat = Math.Round(Q33, 1);

            // Calculate sum sensible heat in room
            res.dbSumRoomSensibleHeat = Math.Round(Q11 + Q2 + Q31 + Q32 + Q33, 1);
            return res.dbSumRoomSensibleHeat;
        }

        // Tổng nhiệt hiện của không khí ngoài trời đưa vào phòng QhN = QhN1 + QhN2
        /// <summary>
        /// Method to calculate summ sensible heat out side of room (QhN)
        /// </summary>
        /// <returns>summ sensible heat out side of room</returns>
        public double CalculateSumOutSideSensibleHeat()
        {
            double QhN1 = CalculateOutSideAirActiveSensibleHeat();
            double QhN2 = CalculateOutSideAirSensibleHeat();
            res.dbSumOutSideSensibleHeat = Math.Round(QhN1 + QhN2, 1);
            return res.dbSumOutSideSensibleHeat;
        }

        //  Nhiệt hiện do không khí ngoài trời chủ động đưa vào phòng QhN1
        /// <summary>
        /// Method to calculate sensible heat of out side active air (QhN1)
        /// </summary>
        /// <returns>sensible heat of out side active air</returns>
        public double CalculateOutSideAirActiveSensibleHeat()
        {
            if (inter.dbDensityPeople != 0)
            {
                dbstandardAir = inter.dbAirMountForOnePeople * ((dblength * dbwidth) / inter.dbDensityPeople);
            }
            else
            {
                dbstandardAir = 0;
            }
            res.dbOutSideAirActiveSensibleHeat = Math.Round(1.23 * dbstandardAir * (dbOutSideTemperature - dbinsideTemperature), 1);
            return res.dbOutSideAirActiveSensibleHeat;
        }

        //  Nhiệt hiện do lượng không khí ngoài trời lọt qua khe cửa QhN2
        /// <summary>
        /// Method to calculate sensible heat of out side air (QhN2)
        /// </summary>
        /// <returns>sensible heat of out side air</returns>
        public double CalculateOutSideAirSensibleHeat()
        {
            res.dbOutSideAirSensibleHeat = Math.Round(0.39 * dbvolume * dbairCoefficient * (dbOutSideTemperature - dbinsideTemperature), 1);
            return res.dbOutSideAirSensibleHeat;
        }
        #endregion

        #region Latent Heat Calculation
        //  Tổng nhiệt ẩn Qa = Qaf + QaN
        /// <summary>
        /// Method ro calculate sum latent heat of room (Qa)
        /// </summary>
        /// <returns>sum latent heat of room</returns>
        public double CalculateSumLatentHeat()
        {
            double Qaf = CalculateSumRoomLatentHeat();
            double QaN = CalculateSumOutSideLatentHeat();
            res.dbSumLatentHeat = Math.Round(Qaf + QaN, 1);
            return res.dbSumLatentHeat;
        }

        // Tổng nhiệt ẩn tỏa ra từ phòng Qaf
        /// <summary>
        /// Method to calculate sum latent heat in room (Qaf)
        /// </summary>
        /// <returns>sum latent heat in room</returns>
        public double CalculateSumRoomLatentHeat()
        {
            double Qaf = inter.CalculatePeopleLatentHeat(dblength * dbwidth);
            res.dbSumRoomLatentHeat = Math.Round(Qaf, 1);
            return res.dbSumRoomLatentHeat;
        }

        //  Tổng nhiệt ẩn của không khí ngoài trời đưa vào phòng QaN = QaN1 + QaN2
        /// <summary>
        /// Method to calculate sum latent heat out side of room (QaN)
        /// </summary>
        /// <returns>sum latent heat out side of room</returns>
        public double CalculateSumOutSideLatentHeat()
        {
            double QaN1 = CalculateOutSideAirActiveLatentHeat();
            double QaN2 = CalculateOutSideAirLatentHeat();
            res.dbSumOutSideLatentHeat = Math.Round(QaN1 + QaN2, 1);
            return res.dbSumOutSideLatentHeat;
        }

        //  Nhiệt ẩn do không khí từ ngoài trời chủ động đưa vào phòng QaN1
        /// <summary>
        /// Method to calculate latent heat of out side active air (QaN1)
        /// </summary>
        /// <returns>latent heat of out side active air</returns>
        public double CalculateOutSideAirActiveLatentHeat()
        {
            if (inter.dbDensityPeople != 0)
            {
                dbstandardAir = inter.dbAirMountForOnePeople * ((dblength * dbwidth) / inter.dbDensityPeople);
            }
            else
            {
                dbstandardAir = 0;
            }
            res.dbOutSideAirActiveLatentHeat = Math.Round(3 * dbstandardAir * (dboutsideVaporContains - dbinsideVaporContains), 1);
            return res.dbOutSideAirActiveLatentHeat;
        }

        //  Nhiệt ẩn của không khí lọt vào phòng QaN2
        /// <summary>
        /// Method to calculate latent heat of out side air (QaN2)
        /// </summary>
        /// <returns>latent heat of out side air</returns>
        public double CalculateOutSideAirLatentHeat()
        {
            res.dbOutSideAirLatentHeat = Math.Round(0.84 * dbvolume * (dboutsideVaporContains - dbinsideVaporContains), 1);
            return res.dbOutSideAirLatentHeat;
        }
        #endregion

        /// <summary>
        /// method to copy Room object to a new object
        /// </summary>
        /// <returns>a new object is Room object type</returns>
        public object Clone()
        {
            object clone;
            try
            {
                using (MemoryStream stream = new MemoryStream())
                {

                    BinaryFormatter formatter = new BinaryFormatter();

                    // Serialize this object

                    formatter.Serialize(stream, this);

                    stream.Position = 0;

                    // Deserialize to another object

                    clone = formatter.Deserialize(stream);

                }
                return clone;
            }
            catch (Exception e)
            {
                return e;
            }
        }
    }
}
